package com.world.login.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpStatus;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.signers.JWTSigner;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.world.business.user.domain.User;
import com.world.business.user.service.IUserService;
import com.world.common.constants.PromptConstants;
import com.world.common.constants.RedisKeyConstants;
import com.world.common.enumeration.DelFlagEnum;
import com.world.common.exception.BusinessException;
import com.world.common.security.SecurityUtils;
import com.world.login.domain.query.LoginRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 登录
 *
 * @author WangYX
 * @version 1.0.0
 * @date 2023/06/01 11:17
 */
@Service
public class LoginServiceImpl implements ILoginService {

    @Resource
    private IUserService userService;
    @Resource
    private JWTSigner signer;
    @Resource
    private RedisTemplate<String, Long> redisTemplate;

    @Override
    public String login(LoginRequest request) {

        //根据用户名查询用户
        LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery(User.class);
        queryWrapper.eq(User::getLoginName, request.getUserName());
        queryWrapper.eq(User::getDelFlag, DelFlagEnum.NORMAL.getCode());
        User one = userService.getOne(queryWrapper);

        if (BeanUtil.isEmpty(one)) {
            throw new BusinessException(HttpStatus.HTTP_BAD_REQUEST, PromptConstants.ACCOUNT_ERROR);
        }

        String password = one.getPassword();
        if (StrUtil.isBlank(password)) {
            throw new BusinessException(HttpStatus.HTTP_INTERNAL_ERROR, PromptConstants.DATE_NOT_INTI);
        }

        if (!checkPassword(request, one)) {
            throw new BusinessException(HttpStatus.HTTP_BAD_REQUEST, PromptConstants.ACCOUNT_ERROR);
        }
        return createToken(one);
    }

    @Override
    public void logout() {
        Long id = SecurityUtils.getLoginUser().getId();
        redisTemplate.delete(RedisKeyConstants.LOGIN_KEY + id);
    }

    /**
     * 校验密码
     *
     * @param request 账密
     * @param user    用户信息
     * @return {@link boolean}
     * @author WangYX
     * @date 2023/06/01 12:36
     */
    private boolean checkPassword(LoginRequest request, User user) {
        MD5 md5 = MD5.create();
        String password = md5.digestHex(request.getPassword() + "-" + user.getSalt());
        return user.getPassword().equals(password);
    }

    /**
     * 创建token
     *
     * @param user 用户数据
     * @return {@link String}
     * @author WangYX
     * @date 2023/06/01 14:06
     */
    public String createToken(User user) {
        //签发时间
        DateTime date = DateUtil.date();
        //当前时间往后偏移2个小时
        DateTime offset = DateUtil.offset(date, DateField.HOUR_OF_DAY, 2);

        String token = JWT.create()
                .setPayload("id", user.getId())
                .setPayload("name", user.getName())
                .setPayload("loginName", user.getLoginName())
                .setIssuedAt(date)
                .setExpiresAt(offset)
                .setSigner(signer)
                .sign();

        //缓存用户到redis中，用以退出登录时用
        redisTemplate.opsForValue().set(RedisKeyConstants.LOGIN_KEY + user.getId(), user.getId(), 2, TimeUnit.HOURS);
        return token;
    }


}
